"""
GomerX 日志记录工具
用于记录机器人运行过程中的事件和错误
"""

# 导入必要的系统模块
import os  # 用于文件和目录操作
import time  # 用于时间相关功能
from datetime import datetime  # 用于日期时间处理
from enum import Enum  # 用于创建枚举类型


class LogLevel(Enum):
    """日志级别枚举
    定义了不同的日志级别，数值越大优先级越高
    """
    DEBUG = 1    # 调试信息：用于开发过程中的详细信息
    INFO = 2     # 一般信息：记录程序正常运行的关键步骤
    WARNING = 3  # 警告信息：表示可能的问题，但不影响程序运行
    ERROR = 4    # 错误信息：记录程序运行中的错误
    CRITICAL = 5 # 严重错误：记录导致程序无法继续运行的严重问题


class Logger:
    """日志记录器
    负责将日志消息写入文件并输出到控制台
    """
    
    def __init__(self, log_dir="logs", log_level=LogLevel.INFO):
        """初始化日志记录器
        
        Args:
            log_dir: 日志文件目录，默认为"logs"
            log_level: 日志级别，默认为INFO级别
        """
        # 保存日志目录和级别
        self.log_dir = log_dir
        self.log_level = log_level
        
        # 检查日志目录是否存在，不存在则创建
        if not os.path.exists(log_dir):
            os.makedirs(log_dir)
        
        # 按当前日期设置日志文件名，格式为：gomerx_YYYY-MM-DD.log
        today = datetime.now().strftime("%Y-%m-%d")
        self.log_file = os.path.join(log_dir, f"gomerx_{today}.log")
    
    def _write_log(self, level, message):
        """写入日志
        
        这是一个内部方法，用于实际写入日志消息到文件和控制台
        
        Args:
            level: 日志级别（LogLevel枚举值）
            message: 日志消息内容
        """
        # 检查日志级别，只有当前消息级别不低于设置的日志级别时才记录
        if level.value < self.log_level.value:
            return  # 跳过低级别日志
        
        # 格式化时间戳，格式为：YYYY-MM-DD HH:MM:SS
        timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        # 组合完整的日志条目：[时间戳] [级别] 消息
        log_entry = f"[{timestamp}] [{level.name}] {message}\n"
        
        # 尝试将日志写入文件
        try:
            with open(self.log_file, "a") as f:  # 以追加模式打开文件
                f.write(log_entry)
        except Exception as e:
            # 如果写入失败，输出错误信息到控制台
            print(f"写入日志失败: {e}")
        
        # 同时将日志输出到控制台（去除末尾换行符）
        print(log_entry.strip())
    
    def debug(self, message):
        """记录调试信息
        
        用于记录程序运行过程中的详细信息，通常只在开发和调试时使用
        
        Args:
            message: 调试信息内容
        """
        self._write_log(LogLevel.DEBUG, message)
    
    def info(self, message):
        """记录一般信息
        
        用于记录程序正常运行的关键步骤和状态信息
        
        Args:
            message: 一般信息内容
        """
        self._write_log(LogLevel.INFO, message)
    
    def warning(self, message):
        """记录警告信息
        
        用于记录可能的问题，这些问题不会导致程序停止，但可能需要注意
        
        Args:
            message: 警告信息内容
        """
        self._write_log(LogLevel.WARNING, message)
    
    def error(self, message):
        """记录错误信息
        
        用于记录程序运行中的错误，这些错误可能影响部分功能但不导致程序崩溃
        
        Args:
            message: 错误信息内容
        """
        self._write_log(LogLevel.ERROR, message)
    
    def critical(self, message):
        """记录严重错误信息
        
        用于记录导致程序无法继续运行的严重问题
        
        Args:
            message: 严重错误信息内容
        """
        self._write_log(LogLevel.CRITICAL, message)
    
    def set_log_level(self, level):
        """设置日志级别
        
        只有等于或高于此级别的日志才会被记录
        
        Args:
            level: 新的日志级别（LogLevel枚举值）
        """
        self.log_level = level
    
    def get_log_file_path(self):
        """获取当前日志文件路径
        
        Returns:
            str: 当前日志文件的完整路径
        """
        return self.log_file


# 全局日志记录器实例，初始为None
_global_logger = None


def get_logger(log_dir="logs", log_level=LogLevel.INFO):
    """获取全局日志记录器实例
    
    使用单例模式确保整个应用程序使用同一个日志记录器实例
    
    Args:
        log_dir: 日志文件目录，默认为"logs"
        log_level: 日志级别，默认为INFO级别
    
    Returns:
        Logger: 日志记录器实例
    """
    global _global_logger  # 引用全局变量
    
    # 如果全局日志记录器尚未创建，则创建一个新实例
    if _global_logger is None:
        _global_logger = Logger(log_dir, log_level)
    
    return _global_logger


def log_function_call(func):
    """装饰器：记录函数调用
    
    自动记录函数的调用、执行时间和结果/错误
    
    Args:
        func: 被装饰的函数
    
    Returns:
        包装后的函数，会在执行前后记录日志
    """
    def wrapper(*args, **kwargs):
        # 获取全局日志记录器
        logger = get_logger()
        # 记录函数调用开始
        logger.debug(f"调用函数: {func.__name__}")
        
        # 记录开始时间
        start_time = time.time()
        try:
            # 执行原函数
            result = func(*args, **kwargs)
            # 计算执行时间
            elapsed_time = time.time() - start_time
            # 记录成功执行
            logger.debug(f"函数 {func.__name__} 执行成功，耗时: {elapsed_time:.2f}秒")
            return result
        except Exception as e:
            # 计算执行时间
            elapsed_time = time.time() - start_time
            # 记录执行失败和错误信息
            logger.error(f"函数 {func.__name__} 执行失败，耗时: {elapsed_time:.2f}秒，错误: {str(e)}")
            # 重新抛出异常
            raise
    
    return wrapper


class PerformanceLogger:
    """性能日志记录器
    
    专门用于测量和记录代码执行性能
    """
    
    def __init__(self, logger=None):
        """初始化性能日志记录器
        
        Args:
            logger: 日志记录器实例，如果为None则使用全局日志记录器
        """
        # 使用提供的日志记录器或全局日志记录器
        self.logger = logger or get_logger()
        # 用于存储多个计时器的字典
        self.timers = {}
    
    def start_timer(self, name):
        """开始计时
        
        为指定名称的计时器记录开始时间
        
        Args:
            name: 计时器名称，用于标识不同的计时器
        """
        # 记录当前时间作为开始时间
        self.timers[name] = time.time()
        # 记录计时开始日志
        self.logger.debug(f"开始计时: {name}")
    
    def end_timer(self, name):
        """结束计时并记录
        
        计算指定计时器的运行时间并记录到日志
        
        Args:
            name: 计时器名称
        
        Returns:
            float: 耗时（秒）
        """
        # 检查计时器是否存在
        if name not in self.timers:
            self.logger.warning(f"计时器 {name} 不存在")
            return 0  # 返回0表示无效计时
        
        # 计算耗时
        elapsed_time = time.time() - self.timers[name]
        # 记录耗时信息
        self.logger.info(f"计时器 {name} 耗时: {elapsed_time:.2f}秒")
        # 从字典中移除该计时器
        del self.timers[name]
        return elapsed_time
    
    def measure_function(self, func):
        """装饰器：测量函数执行时间
        
        自动测量被装饰函数的执行时间
        
        Args:
            func: 被装饰的函数
        
        Returns:
            包装后的函数，会在执行前后自动计时
        """
        def wrapper(*args, **kwargs):
            # 开始计时
            self.start_timer(func.__name__)
            try:
                # 执行原函数
                result = func(*args, **kwargs)
                return result
            finally:
                # 无论是否发生异常，都结束计时
                self.end_timer(func.__name__)
        
        return wrapper


class TaskLogger:
    """任务日志记录器
    
    用于记录多步骤任务的执行过程和总耗时
    """
    
    def __init__(self, task_name, logger=None):
        """初始化任务日志记录器
        
        Args:
            task_name: 任务名称，用于标识不同的任务
            logger: 日志记录器实例，如果为None则使用全局日志记录器
        """
        self.task_name = task_name
        # 使用提供的日志记录器或全局日志记录器
        self.logger = logger or get_logger()
        # 任务开始时间，初始为None
        self.start_time = None
        # 任务步骤列表，每个元素为(步骤名称, 时间)的元组
        self.steps = []
    
    def start(self):
        """开始任务
        
        记录任务开始时间并输出开始日志
        """
        # 记录当前时间作为开始时间
        self.start_time = time.time()
        # 记录任务开始日志
        self.logger.info(f"开始任务: {self.task_name}")
    
    def log_step(self, step_name):
        """记录任务步骤
        
        记录任务中的每个步骤及其耗时
        
        Args:
            step_name: 步骤名称
        """
        # 记录当前时间
        step_time = time.time()
        # 将步骤添加到步骤列表
        self.steps.append((step_name, step_time))
        
        # 如果这不是第一个步骤，计算与上一步骤的间隔时间
        if len(self.steps) > 1:
            prev_step, prev_time = self.steps[-2]
            elapsed = step_time - prev_time
            # 记录步骤及其耗时
            self.logger.info(f"任务步骤: {step_name} (耗时: {elapsed:.2f}秒)")
        else:
            # 第一个步骤只记录名称
            self.logger.info(f"任务步骤: {step_name}")
    
    def end(self, success=True):
        """结束任务
        
        计算任务总耗时并记录结束日志
        
        Args:
            success: 任务是否成功完成，默认为True
        """
        # 检查任务是否已开始
        if self.start_time is None:
            self.logger.warning(f"任务 {self.task_name} 未开始")
            return
        
        # 计算总耗时
        elapsed_time = time.time() - self.start_time
        
        # 根据成功与否记录不同级别的日志
        if success:
            self.logger.info(f"任务 {self.task_name} 完成，总耗时: {elapsed_time:.2f}秒")
        else:
            self.logger.error(f"任务 {self.task_name} 失败，总耗时: {elapsed_time:.2f}秒")
    
    def __enter__(self):
        """上下文管理器入口
        
        使TaskLogger可以用with语句使用
        
        Returns:
            TaskLogger: 自身实例
        """
        self.start()
        return self
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        """上下文管理器出口
        
        退出with语句时自动调用，根据是否有异常判断任务是否成功
        
        Args:
            exc_type: 异常类型
            exc_val: 异常值
            exc_tb: 异常追踪
        """
        # 如果没有异常，则任务成功；否则失败
        success = exc_type is None
        self.end(success)


if __name__ == "__main__":
    # 示例用法，当直接运行此文件时执行
    
    # 获取全局日志记录器
    logger = get_logger()
    # 记录日志系统初始化完成
    logger.info("日志系统初始化完成")
    
    # 创建性能日志记录器
    perf_logger = PerformanceLogger()
    
    # 使用装饰器测量函数执行时间
    @perf_logger.measure_function
    def example_function():
        """示例函数"""
        # 模拟耗时操作
        time.sleep(0.5)
        # 记录调试信息
        logger.debug("示例函数执行中")
        return "示例结果"
    
    # 调用示例函数
    result = example_function()
    
    # 使用任务日志记录器和上下文管理器
    with TaskLogger("示例任务") as task_logger:
        # 记录任务步骤
        task_logger.log_step("步骤1")
        time.sleep(0.2)  # 模拟步骤耗时
        
        task_logger.log_step("步骤2")
        time.sleep(0.3)  # 模拟步骤耗时
        
        task_logger.log_step("步骤3")
        time.sleep(0.1)  # 模拟步骤耗时